<?php
namespace control;
// 销售合同
class salesContractClass extends adIndexClass
{
    private const page = 'salesContract'; # 权限
    private const table = 'sales_contract'; # 数据表
    private const tableMx = 'sales_contract_detail';         //销售合同明细表
    private const tableAddr = 'sales_contract_address'; # 地址表
    private const tablePay = 'sales_contract_payback'; # 回款表
    private const title = '销售合同';
    private const stateOption = ['草稿', '审核中', '已通过'];



    /*列表页-查询条件*/
    public function clientContractOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('salesContract.homeSearch.signedDate') => text(['name' => 'signedDate', 'laydate' => ['range' => '~', 'type' => 'date'],]).
                        hidden(array("name" => "targetId", "value" => $this->get('id'))),
                    L('salesContract.home.orderNo')   => text(array("name" => "orderNo")),
                    L('salesContract.home.name')   => text(array("name" => "name")),
                ],
                [
                    L('salesContract.home.type')  => select(["name" => "type", 'option' => ['主合同', '补充协议']]),
                    L('salesContract.home.salesman') => selectMultiple(['table' => 'staff', 'sqlField' => 'name', 'sqlId' => 'stid', 'name' => 'salesman']),
                    L('salesContract.home.state') => select(["name" => "state", 'option' => self::stateOption]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /**
     * 客户页卡报价单
     * @return bool|string
     */
    public function clientContract(): bool|string
    {
        $html = $this->clientContractOptions(false);
        $button = "";
        //返回
        $json['html'] = $this->search($html, layout: 'pop', toolButton: $button);
        return json_encode($json, 320);
    }

    public function clientContractSearch(): bool|string
    {
        $khid = $this->post('targetId');
        //查询结果
        $equal = [
            'type' => $this->post('type'),
            'salesman' => $this->post('salesman'),
            'state' => $this->post('state'),
            'coid'=>self::$coid
        ];
        $like = [
            'orderNo' => $this->post('orderNo'),
            'name' => $this->post('name'),
        ];
        //生成查询语句
        $where = search([
                "=" => $equal,
                "like" => $like,
            ]) . " and clientId = '$khid'";
        if ($this->post('signedDate')) {
            $where .= self::timeComparison($this->post('signedDate'), 'date', 'signedDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'time',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        $page = $this->page(["table" => self::table, "where" => $where, "order" => $orderBy['orderBy']]);
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array("");
        //获取记录
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                "detail" => ["title" => L('salesContract.homeSearch.detail'), "click" => "newIframe('".L('salesContract.homeSearch.detail')."','" . root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=detail&id=' . $array['id'] . "')"],
            );
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case "money":
                        $row[] = self::lostZero($array['money'], 'amount');
                        break;
                    case "salesman":
                        $row[] = self::findStaff($array['salesman']);
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = "<form name='contractForm'>" . $li . "</form>" . $page['button'] . clear;
        return json_encode($json, 320);
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('salesContract.homeSearch.signedDate') => text(['name' => 'signedDate', 'laydate' => ['range' => '~', 'type' => 'date'],]),
                    L('salesContract.home.orderNo')   => text(array("name" => "orderNo")),
                    L('salesContract.home.name')   => text(array("name" => "name")),
                ],
                [
                    '客户' => clientClass::kehuSelect(array('name'=>'clientId', "title" => '')),
                    L('salesContract.home.type')  => select(["name" => "type", 'option' => ['主合同', '补充协议']]),
                    L('salesContract.home.salesman') => selectMultiple(['table' => 'staff', 'sqlField' => 'name', 'sqlId' => 'stid', 'name' => 'salesman']),
                ],
                [
                    L('salesContract.home.state') => select(["name" => "state", 'option' => self::stateOption]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /*销售合同入口页*/
    public function home()
    {
        $html = $this->homeOptions(false);
        //控件
        $button = "";
        $url = root . "control/adIndex.html?cla=" . self::page;
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"newIframe('" . L('salesContract.homeSearch.detail') . "','" . $url . "&fun=edit')\" class='spanButton'>".L('salesContract.homeSearch.new')."</span>\n";
        }
        if ($this->power(self::page, "del")) {
            $button .= spanButton(['name' => L('salesContract.homeSearch.del'), 'page' => self::page, 'fun' => 'operate', 'para' => ['act' => 'del'], 'first' => true]);
        }
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /*销售合同列表*/
    public function homeSearch()
    {
        //查询结果
        $where = ' 1=1 ';
        $equal = [
            'clientId' => $this->post('clientId'),
            'type' => $this->post('type'),
            'salesman' => $this->post('salesman'),
            'state' => $this->post('state'),
            'coid'=>self::$coid
        ];
        $like = [
            'orderNo' => $this->post('orderNo'),
            'name' => $this->post('name'),
        ];
        //生成查询语句
        $where .= search([
            "=" => $equal,
            "like" => $like,
        ]);
        // 查询自己
        if (!$this->power(self::page, "seeAll")) {
            $where .= " and stid = '" . self::$stid . "' ";
        }
        if ($this->post('signedDate')) {
            $where .= self::timeComparison($this->post('signedDate'), 'date', 'signedDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'time',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        $page = $this->page(["table" => self::table, "where" => $where, "order" => $orderBy['orderBy']]);
        $_SESSION[self::page]['where'] = $where;
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        $url = root . "control/adIndex.html?cla=" . self::page;
        //获取记录
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = [
                "box" => ["name" => "listId", "value" => $array['id']],
                "detail" => ["title" => L('salesContract.homeSearch.detail'), "click" => "newIframe('".L('salesContract.homeSearch.detail')."','" . root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=detail&id=' . $array['id'] . "')"],
                "edit" => $array['state'] == '草稿' ? ["title" => L('salesContract.homeSearch.edit'), "click" => "newIframe('".L('salesContract.homeSearch.edit')."','" . root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=edit&id=' . $array['id'] . "')"] : [],
            ];
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case "money":
                        $row[] = self::lostZero($array['money'], 'amount');
                        break;
                    case "salesman":
                        $row[] = self::findStaff($array['salesman']);
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        $totalMoney = find([
            'table'  => self::table,
            'single' => $where,
            'field'  => "ifnull(sum(money),0) as money",
        ]);
        $total    = [
            'money'      => self::lostZero($totalMoney['money']),
        ];
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
            "total"       => $total,
        ));
        //返回
        $json['html'] = "<form name='listForm'>" . $li . "</form>" . $page['button'] . clear;
        return json_encode($json, 320);
    }

    /**
     * 编辑页
     *
     * @return string
     */
    public function edit(): string
    {
        $id   = $this->get('id') ?: suiji();
        $info = query(self::table, " id = '" . $id . "' ");
        $button[] = [
            "name"  => "保存",
            "type"  => "点击事件",
            "title" => "保存",
            'fun'   => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&fun=editEdit')",
        ];
//        $button[] = [
//            "name"  => "保存并提交",
//            "type"  => "点击事件",
//            "title" => "保存",
//            'fun'   => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&fun=saveAndCommit')",
//            'style' => 'li-btn-blue-bg',
//        ];
//        $tr[]     = ['', '产品编码', '产品名称', '规格型号', must.'单位', must.'数量', must.'单价(' . static::$unit . ')', '备注'];
        $tr[]     = ['操作', '物料编码', '物料名称', '规格型号', '单位', '单价(' . static::$unit . ')','数量', '备注'];
        $result   = find(['table' => self::tableMx, 'where' => "orderId = '$info[id]' order by list"]);
        $totalArr = ['total_num' => 0, 'total_tax_money' => 0, 'total_money' => 0];
        foreach ($result['array'] as $k => $array) {
            $material                    = query('material', " id = '$array[materialId]'");
            $tr[]                        = [
                componentClass::tablePperation($k + 1, "delTableRow(this);calculateTotal()") .
                hidden(['name' => 'mxId[]', 'value' => $array['id']]) .
                hidden(['name' => 'materialId[]', 'value' => $array['materialId']]),
                $material['code'],
                $material['name'],
                $material['model'],
                select(['name' => 'unit[]', 'data' => ['unit' => $array['unit']], 'option' => machiningOrderClass::unitOption($material['id']), 'title' => '单位', 'value' => $array['unit']]),
                text(['name' => 'price[]', 'type' => 'text', 'other' => self::digitalFiltering('pricePrecision'), 'value' => $array['price'] ? self::lostZero($array['price'], 'pricePrecision') : '']),
                text(['name' => 'num[]', 'type' => 'text', 'other' => self::digitalFiltering('int'), 'value' => $array['num'] ? self::lostZero($array['num'], 'pricePrecision') : '']),
                text(['name' => 'mxText[]', 'class' => 'text textPrice', 'value' => $array['text']]),
            ];
            $totalArr['total_num']       += $array['num'];
            $totalArr['total_tax_money'] += $array['taxMoney'];
            $totalArr['total_money']     += $array['money'];
        }
        $total = [];
        $table      = $this->listTable(['tr' => $tr, 'end' => true, 'total' => $total]);
        $mxButton   = <<<efo
                    <span class="smallButton" onclick="layer('{$this->get('cla')}','addMx',$('form[name=saleOrderEditForm]').serialize())">选择产品</span>
efo;
        $settlement = array_merge(para('supplierSettlement', '，'), ['月结']);
        //表单
        $data['button'] = $this->tableShowButton($button);
        $body           = $this->edit4([
            '基本信息' => [
                [
                    must . "合同编号：" =>
                        text(['name' => "orderNo", 'class' => 'text', 'value' => $info['orderNo']?:codeTemplateClass::generateCode(self::page, [
                            'prefix' => 'XSHT' . date('Ymd'),
                            'table' => self::table,
                            'field' => 'orderNo',
                            'where' => " and coid = '" . self::$coid . "' ",
                        ], [])]),
                    must . "合同名称：" => text(['name' => "name", 'class' => 'text', 'value' => $info['name']]),
                    must . "客户："   => clientClass::kehuSelect(array('name'=>'clientId','value'=> $this->get('khid') ?: $info['clientId'])),
                    must . "合同类别：" => radio(['name' => "type", 'class' => 'text', 'checked' => $info['type'] ?: '主合同', 'value' => ['主合同', '补充协议']]),
                ],
                [
                    must ."签订日期：" => text(['name' => "signedDate", 'class' => 'text', 'value' => $info['signedDate'], 'laydate' => [],]),
                    "有效开始日期：" => text(['name' => "startDate", 'class' => 'text', 'value' => $info['startDate'], 'laydate' => [],]),
                    "有效结束日期：" => text(['name' => "endDate", 'class' => 'text', 'value' => $info['endDate'], 'laydate' => [],]),
                ],
                [
                    must . "结算方式：" => radio(['name' => 'settlementType', 'change' => 'settlementDayDefault', 'checked' => $info['settlementType'] ?: $settlement[0], 'value' => $settlement]) .
                        "&nbsp;" .
                        text(['name' => 'settlementDay', 'type' => 'number', 'value' => $info['settlementDay'] ?: '', 'title' => '结算周期']),
//                    "押运员："         =>
//                        "<div class='full'>" .
//                        selectMultiple([
//                            "name"     => "delivery_manage",
//                            "value"    => $info['delivery_manage'],
//                            'table'    => "staff",
//                            'where'    => " 1=1 ",
//                            'sqlId'    => 'stid',
//                            'sqlField' => 'name',
//                            'title'    => '请选择',
//                        ]) .
//                        "</div>",
//                    "驾驶员："         =>
//                        "<div class='full'>" .
//                        selectMultiple([
//                            "name"     => "delivery_name",
//                            "value"    => $info['delivery_name'],
//                            'table'    => "staff",
//                            'where'    => " 1=1 ",
//                            'sqlId'    => 'stid',
//                            'sqlField' => 'name',
//                            'title'    => '请选择',
//                        ]) .
//                        "</div>",
//                    "选择车辆："         =>
//                        "<div class='full'>" .
//                        selectMultiple([
//                            "name"     => "car_id",
//                            "value"    => $info['car_id'],
//                            'table'    => "logistics_car",
//                            'where'    => " 1=1 and state='正常' and coid='".self::$coid."'",
//                            "field"    => "id,CONCAT(shortName, '',carNo) AS car_name",
//                            'sqlId'    => 'id',
//                            'sqlField' => 'car_name',
//                            'title'    => '请选择',
//                        ]) .
//                        "</div>",
                ],
                [
                    "备注：" => textarea(["name" => "text", 'class' => 'text', "value" => $info['text']]),
                ],
            ]
        ]);
        $body           .= $this->editList([
            'id'     => 'materialTable',
            'title'  => '订单明细',
            'button' => $mxButton,
            'html'   => $table,
        ]);
        $data['html'] = $this->pageEdit([
            "html"   => $body,
            'hidden' => hidden(['name' => 'id', 'value' => $id]),
        ]);
        $data['html'] .= <<<efo
<script>
//跳转详情
function jumpPage(url){
    let khid = $("[name='khid']").val();
    if(!khid){
        warn('请选择客户','error')
        return
    }
    newIframe('客户详情',url+'&id='+khid)
}

function addRow(){
    var type = arguments[0]
    if(type === 'contract'){
        $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addContractEdit',$("form[name='contractForm']").serialize(),function(res) {
            $("#materialTable tbody").append(res.html);
            resetNumber($("#materialTable tbody"))
        },'json');
    }else{
        $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addMxEdit',$("form[name='mxForm']").serialize(),function(res) {
            $("#materialTable tbody").append(res.html);
            resetNumber($("#materialTable tbody"))
        },'json');
    }
}
function chooseRec(){
     $('#saleOrderReceiver').hide();
      $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=getReceiver',$("form[name='recForm']").serialize(),function(res) {
          $("[name='contactName']").val(res.data.name);
          $("[name='contactTel']").val(res.data.tel);
          $("[name='address']").val(res.data.address);
    },'json');
}
</script>

efo;//. $this->editJs()
        //返回
        return $this->tab($data);
    }

    public function editEdit()
    {
        $id                    = $this->post('id') ?: self::getId();
        $mxIdArr               = $this->post('mxId') ?: [];
        $materialIdArr         = $this->post('materialId');
        $numArr                = $this->post('num');
        $unitArr               = $this->post('unit');
        $priceArr              = $this->post('price');
        $mxTextArr             = $this->post('mxText');
        $field                 = [
            'orderNo' => $this->post('orderNo'),
            'name' => $this->post('name'),
            'clientId' => $this->post('clientId'),
            'type' => $this->post('type'),
            'signedDate' => $this->post('signedDate'),
            'startDate' => $this->post('startDate'),
            'endDate' => $this->post('endDate'),
            'money' => self::formattingFigure($this->post('money'), 'amount'),
            'payType' => $this->post('payType'),
            'text' => $this->post('text'),
            'settlementType'  => $this->post('settlementType'),
            'settlementDay'   => $this->post('settlementDay'),
            'delivery_method' => $this->post('delivery_method'),
            'car_id'          => $this->post('car_id'),
            'delivery_manage' => $this->post('delivery_manage'),
        ];
        $where                 = " id = '$id' ";
        $info                  = query(self::table, $where);
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (!empty($info['id']) && $info['state'] == '已确认') {
            $json['warn'] = '此销售合同已确认，不能修改';
        } else {
            $json['warn'] = '';
            if (empty($json['warn'])) {
                //$kehu = query('kehu', "khid = '$field[khid]'");
                $this->startTrans();
                $isPass = true;//事务通过标志
                if (!$info['id']) {
                    $field = array_merge($field, [
                        'id' => $id,
                        'coid' => self::$coid,
                        'state' => '草稿',
                        'stid' => $this->control['stid'],
                        'time' => $this->time
                    ]);
                    $json['warn'] = static::insert(["table" => self::table, "field" => $field,]);
                } else {
                    $json['warn'] = static::update([
                        "table" => self::table,
                        "field" => $field,
                        "where" => $where,
                    ]);
                }
                //添加或更新明细
                if (is_array($mxIdArr)) {
                    foreach ($mxIdArr as $k => $nid) {
                        $mx           = query(self::tableMx, "id = '$nid'");
                        $numArr[$k]   = self::formattingFigure($numArr[$k], 'numPrecision');
                        $priceArr[$k] = self::formattingFigure($priceArr[$k], 'pricePrecision');
                        //数据格式处理
                        $taxRateArr[$k] = floatval($taxRateArr[$k] ?? 0) / 100;//税率从百分比转为小数
                        if (!empty($mx['id'])) {
                            //更新
                            $warn = static::update([
                                "table" => self::tableMx,
                                "field" => [
                                    'materialId'         => $materialIdArr[$k],
                                    'unit'               => $unitArr[$k],
                                    'num'                => $numArr[$k],
                                    'price'              => $priceArr[$k],
                                    'taxMoney'           => 0,//税额
                                    'moneyWithOutTax'    => 0,//不含税金额
                                    'money'              => 0,//价税合计
                                    'rate'               => 0,
                                    'text'               => $mxTextArr[$k],
                                ],
                                "where" => " id = '$nid'",
                            ]);
                        } else {
                            //新增
                            $warn = static::insert([
                                "table" => self::tableMx,
                                "field" => [
                                    'id'                 => $nid,
                                    'orderId'            => $id,
                                    'coid'               => self::$coid,
                                    'materialId'         => $materialIdArr[$k],
                                    'unit'               => $unitArr[$k],
                                    'num'                => $numArr[$k],
                                    'price'              => $priceArr[$k],
                                    'taxMoney'           => 0,//税额
                                    'moneyWithOutTax'    => 0,//不含税金额
                                    'money'              => 0,//价税合计
                                    'rate'               => 0,
                                    'text'               => $mxTextArr[$k],
                                ],

                            ]);
                        }
                        if (!in_array($warn, ['新增成功', '更新成功'])) {
                            $isPass       = false;
                            $json['warn'] = $warn;
                            break;
                        }
                    }
                }

                if (in_array($json['warn'], ["新增成功", "更新成功"]) && $isPass) {
                    $this->commitTrans();
                    delete(['table' => self::tableMx, 'where' => " id not in ('" . implode("','", $mxIdArr) . "') and orderId = '$id'"]);
//                    $total = find(['table' => self::tableMx, 'single' => "orderId = '$id'", 'field' => "ifnull(sum(num),0) as num,ifnull(sum(money),0) as money"]);
//                    update(['table' => self::table, 'field' => ['num' => $total['num'], 'money' => $total['money']], 'where' => "id = '$id'"]);
                    if ($json['warn'] == '新增成功') {
                        self::insertOperateLog($id, self::title, "新建");
                    }
                    //添加日志
                    $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                    $text = $this->control['name'] . $type . "了" . self::title . " id：【" . $id . '】';
                    $this->logText(["type" => self::page, "text" => $text]);
                    //返回
                    $_SESSION['warn'] = $json['warn'];
                    $json['warn']     = 2;
                    $json['href']     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $id;
                } else {
                    $this->rollback();
                }
            }
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 审核按钮
     * @param $info
     * @return array
     */
    public function auditButton($info): array
    {
        if (empty($info['id'])) {
            return [];
        }
        $button = [];
        if ($info['state'] == '草稿' || auditClass::auditFlag(self::table, $info['id'], 'selfChoose')) {
            $button[] = [
                "name" => L('salesContract.auditButton.start'),
                "type" => "弹出层",
                "cla" => 'audit',
                "fun" => "operate",
                'style' => 'li-btn-blue-bg',
                "post" => ["act" => 'start', "id" => $info['id'], 'body' => self::encryptDecrypt(json_encode([
                    'name' => self::title,
                    'table' => self::table,
                    'process' => [
                        // 预览函数
                        'detail' => [
                            'cla' => $this->get('cla'),
                            'fun' => 'detail'
                        ],
                        // 保存函数
                        'save' => [
                            'cla' => $this->get('cla'),
                            'fun' => 'editPageEdit'
                        ],
                        //执行发起时验证函数
                        'before' => [
                            'cla' => $this->get('cla'),
                            'fun' => 'dataValidation',
                            'data'=>$info
                        ],
                        //完成发起后执行函数
                        'after' => [
                            'cla' => $this->get('cla'),
                            'fun' => ''
                        ],
                    ],
                ], 320))],
            ];
        }
        // 审批并判断是否有权限
        if ($info['state'] == '审核中' && auditClass::auditFlag(self::table, $info['id'])) {
            $button[] = [
                "name" => L('salesContract.auditButton.approval'),
                "type" => "弹出层",
                "cla" => 'audit',
                "fun" => "operate",
                // 以下参数固定格式
                "post" => ["act" => 'approval', "id" => $info['id'], 'body' => self::encryptDecrypt(json_encode([
                    'table' => self::table,
                    // 当前状态
                    'state' => $info['state'],
                    // 变更
                    'field' => ['state'],   //变更字段 可多个
                    'value' => [
                        'state' => ['草稿', '已通过'],
                    ],
                    // 审核时回调
                    'process' => [
                        //执行首次审核时验证
                        'before' => [
                            'cla' => $this->get('cla'),
                            'fun' => ''
                        ],
                        //执行末次审核后处理
                        'after' => [
                            'cla' => $this->get('cla'),
                            'fun' => 'useDone',
                            'data' => ['id' => $info['id']]
                        ],
                    ],
                ], 320))],
                'style' => 'li-btn-blue-bg',
            ];
            $button[] = [
                "name" => L('salesContract.auditButton.addApprover'),
                "type" => "弹出层",
                "cla" => 'audit',
                "fun" => "operate",
                "post" => ["act" => 'addApprover', "id" => $info['id'], 'body' => self::encryptDecrypt(json_encode([
                    'table' => self::table
                ], 320))],
            ];
            $button[] = [
                "name" => L('salesContract.auditButton.transfer'),
                "type" => "弹出层",
                "cla" => 'audit',
                "fun" => "operate",
                "post" => ["act" => 'transfer', "id" => $info['id'], 'body' => self::encryptDecrypt(json_encode([
                    'table' => self::table
                ], 320))],
            ];

        }
        // 撤销审批
        if (auditClass::auditFlag(self::table, $info['id'], 'cancel') && $info['state'] != '草稿') {
            $button[] = [
                "name" => L('salesContract.auditButton.cancel'),
                "type" => "弹出层",
                "cla" => 'audit',
                "fun" => "operate",
                "post" => ["act" => 'cancel', "id" => $info['id'], 'body' => self::encryptDecrypt(json_encode([
                    'table' => self::table,
                    // 当前状态
                    'state' => $info['state'],
                    // 变更
                    'field' => ['state'],   //变更字段 可多个
                    'value' => [
                        'state' => ['草稿'],
                    ],
                    'process' => [
                        //完成发起后执行函数
                        'after' => [
                            'cla' => $this->get('cla'),
                            'fun' => ''
                        ],
                    ],
                ], 320))],
            ];
        }
        return $button;
    }

    /**
     * 审批结束后执行
     * @param $data
     */
    public function useDone($data)
    {
        $info = query(self::table, " id = '$data[id]'");
        if (static::total(['table' => self::table, 'where' => "state = '已通过' and clientId = '$info[clientId]'"]) == 1) {
            update(array('table' => self::table, 'field' => ['isFirst' => 1], 'where' => "id = '$info[id]'"));
            update(array('table' => 'kehu', 'field' => ['isDeal' => 1, 'workFlow' => '已签'], 'where' => "khid = '$info[clientId]'"));
        }
    }

    /**
     * Desc : 数组key拼接上字符串
     * User : you name
     * Date : 2024-02-28 17:42
     * @param $array
     * @param $prefix
     * @return array
     */
    public function prefixArrayKeys($array, $prefix) {
        $newArray = array();
        foreach ($array as $key => $value) {
            $newKey = $prefix . $key;
            $newArray[$newKey] = $value;
        }
        return $newArray;
    }

    /**
     * Desc : 回款计划明细
     * User : you name
     * Date : 2024-02-20 14:51
     * @param array $data
     * @return array|false|string
     */
    public function paybackRow($data=[])
    {
        $list = isset($data['list'])?$data['list']:'';
        $type = 'payback';
        $id = isset($data[$type.'id'])&&$data[$type.'id']?$data[$type.'id']:self::getId();
        $field = [$type.'date', $type.'money', $type.'stage', $type.'text'];
        foreach ($field as $item){
            $array[$item] = isset($data[$item])?$data[$item]:$this->post($item);
        }
        $cloneArg = json_encode([
            'cla' => self::page,
            'fun' => 'paybackRow',
            'copy' => $field,
        ],320);
        $delArg = json_encode([
            'empty' => $field,
        ],320);
        $tr = [
            componentClass::tablePperation($list, "delRows(this,$delArg)","cloneRows(this,$cloneArg)", "addRow(this,'$type')"),
            hidden(['name' => $type . 'id[]', 'value' => $id]) .
            text(['name' => $type . 'date[]', 'laydate' => [], 'title' => L('salesContract.editPage.date'), 'value' => $array[$type.'date']]),
            text(['name' => $type . 'money[]', 'type' => 'text', 'other' => self::digitalFiltering(), 'title' => L('salesContract.editPage.money').'（' . static::$unit . '）', 'value' => $array[$type.'money']]),
            select(['name' => $type . 'stage[]', 'title' => L('salesContract.editPage.stage'), 'option' => explode('，', para('salesContractStageOption')), 'value' => $array[$type.'stage']]),
            textarea(['name' => $type . 'text[]', 'title' => L('salesContract.editPage.text'), 'value' => $array[$type.'text']]),
        ];
        if($data){
            return $tr;
        }
        $json['html'] = $this->tableMany(['tr' => [$tr], 'thead' => false]);
        return json_encode($json, 320);
    }

    /**
     * Desc : 收货地址行
     * User : you name
     * Date : 2024-02-20 14:51
     * @param array $data
     * @return array|false|string
     */
    public function addressRow($data=[])
    {
        $list = isset($data['list'])?$data['list']:'';
        $type = 'address';
        $id = isset($data[$type.'id'])&&$data[$type.'id']?$data[$type.'id']:self::getId();
        $field = [$type.'name', $type.'tel', $type.'address'];
        foreach ($field as $item){
            $array[$item] = isset($data[$item])?$data[$item]:$this->post($item);
        }
        $cloneArg = json_encode([
            'cla' => self::page,
            'fun' => 'addressRow',
            'copy' => $field,
        ],320);
        $delArg = json_encode([
            'empty' => $field,
        ],320);
        $tr = [
            componentClass::tablePperation($list, "delRows(this,$delArg)","cloneRows(this,$cloneArg)", "addRow(this,'$type')"),
            hidden(['name' => $type . 'id[]', 'value' => $id]) .
            text(['name' => $type . 'name[]', 'title' => L('salesContract.editPage.name'), 'value' => $array[$type.'name']]),
            text(['name' => $type . 'tel[]', 'title' => L('salesContract.editPage.tel'), 'value' => $array[$type.'tel']]),
            text(['name' => $type . 'address[]', 'title' => L('salesContract.editPage.address'), 'value' => $array[$type.'address']]),
        ];
        if($data){
            return $tr;
        }
        $json['html'] = $this->tableMany(['tr' => [$tr], 'thead' => false]);
        return json_encode($json, 320);
    }



    /*基本资料新增或修改-异步处理*/
    public function editPageEdit()
    {
        $id = $this->post('id') ?: self::getId();
        $field = [
            'orderNo' => $this->post('orderNo'),
            'name' => $this->post('name'),
            'clientId' => $this->post('clientId'),
            'type' => $this->post('type'),
            'signedDate' => $this->post('signedDate'),
            'startDate' => $this->post('startDate'),
            'endDate' => $this->post('endDate'),
            'money' => self::formattingFigure($this->post('money'), 'amount'),
            'payType' => $this->post('payType'),
            'text' => $this->post('text'),
        ];
        // 合同回款
        $type = 'payback';
        $paybackField = [
            'id' => $this->post($type . 'id'),
            'coid' => self::$coid,
            'orderId' => $id,
            'name' => $this->post('name'),
            'date' => $this->post($type . 'date'),
            'money' => $this->post($type . 'money'),
            'stage' => $this->post($type . 'stage'),
            'text' => $this->post($type . 'text'),
            'time' => $this->time,
        ];

        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = L('salesContract.editPageEdit.power');
        } else {
            $kehu = query('kehu', " khid = '{$field['clientId']}' ");
            if ($kehu) {
                $field = array_merge($field, [
                    'clientName' => $kehu['companyName'],
                    'salesman' => $kehu['manager'],
                ]);
            }
            // 开启事务
            $this->startTrans();
            $where = " id = '$id' ";
            $info = query(self::table, $where);
            if (!$info['id']) {
                $field = array_merge($field, [
                    'id' => $id,
                    'coid' => self::$coid,
                    'state' => '草稿',
                    'stid' => $this->control['stid'],
                    'time' => $this->time
                ]);
                $json['warn'] = static::insert(["table" => self::table, "field" => $field,]);
            } else {
                $json['warn'] = static::update([
                    "table" => self::table,
                    "field" => $field,
                    "where" => $where,
                ]);
            }
            if (!in_array($json['warn'], ["新增成功", "更新成功"])) {
                // 事务回滚
                $this->rollback();
            } else {
                if (is_array($paybackField)) {
                    $checkPaybackKey = ['date','money','stage','text'];
                    static::insertArray(self::tablePay, $paybackField, emptyFilter: $checkPaybackKey);
                    if (!empty(current($paybackField))) {
                        delete(['table' => self::tablePay, 'where' => " id NOT IN ('" . implode("','", current($paybackField)) . "') AND orderId = '$id'  "]);
                    }
                }
                // 提交事务
                $this->commitTrans();
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = str_replace(['{{staffName}}','{{type}}','{{id}}'], [$this->control['name'],$type,$id], L('salesContract.editPageEdit.log')) . ($field['name'] ? str_replace(['{{name}}'], [$field['name']], L('salesContract.editPageEdit.contractName')) : '');
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
                $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $id;
                $json['id'] = $id;
            }
        }

        resp:
        return json_encode($json, 320);
    }
    /**
     * Desc : 提交前数据验证
     * User : you name
     * Date : 2023-11-17 16:04
     * @param $info
     * @return string|bool
     */
    public function dataValidation($info): bool|string
    {
        $annotation = [
            'name' => L('salesContract.editPageEdit.name'),
            'clientId' => L('salesContract.editPageEdit.clientId'),
            'type' => L('salesContract.editPageEdit.type'),
            'signedDate' => L('salesContract.editPageEdit.signedDate'),
            'startDate' => L('salesContract.editPageEdit.startDate'),
            'endDate' => L('salesContract.editPageEdit.endDate'),
            'money' => L('salesContract.editPageEdit.money'),
            'text' => L('salesContract.editPageEdit.text'),
        ];
        $rules = [
            'orderNo' => 'required',
            'name' => 'required',
            'clientId' => 'required',
            'type' => 'required',
            'signedDate' => 'required',
            'money' => 'required|numeric',
        ];
        // 校验是否符合规则
        $vt = new \verify();
        $result = $vt->setAliases($annotation)->validate($info, $rules)->isOk();
        if ($result === false) {
            return $vt->getErrs()[0]; // 多个规则提示最前面一条
        }
        if (sqlNum(self::table, "coid = '".self::$coid."' and orderNo = '$info[orderNo]' and id != '" . $info['id'] . "' ") > 0){
            return L('salesContract.editPageEdit.orderNo_repeat_warn');
        }
        $result = find(array('table' => self::tableMx, 'field' => 'id,materialId,unit,num,price', 'where' => "orderId = '$info[id]' order by list"));
        if(count($result['array']) == 0){
            return "请完善合同明细";
        }
        if (static::is_null_array(array_column($result['array'],'materialId'))){
            return '合同明细中【物料】不能为空';
        }
        if (static::is_null_array(array_column($result['array'],'unit'))){
            return '合同明细中【单位】不能为空';
        }
        if(static::is_null_array(array_column($result['array'],'num'),false)){
            return "合同明细中【数量】不能为空，且必须大于0";
        }
        if(static::is_null_array(array_column($result['array'],'price'),false)){
            return "合同明细中【单价】不能为空，且必须大于0";
        }
        return true;
    }


    /**
     * 保存并提交审批
     * @return bool|string
     */
    public function saveAndCommit(): bool|string
    {
        $resultJson = $this->editPageEdit();
        $result = json_decode($resultJson,true);
        if ($result['warn'] == 2){
            $id = $result['id'];
            $info = query(self::table, " id = '$id' ");
            $body = self::encryptDecrypt(json_encode([
                'name' => self::title,
                'table' => self::table,
                'process' => [
                    // 预览函数
                    'detail' => [
                        'cla' => $this->get('cla'),
                        'fun' => 'detail'
                    ],
                    // 保存函数
                    'save' => [
                        'cla' => $this->get('cla'),
                        'fun' => 'editPageEdit'
                    ],
                    //执行发起时验证函数
                    'before' => [
                        'cla' => $this->get('cla'),
                        'fun' => 'dataValidation',
                        'data'=>$info
                    ],
                    //完成发起后执行函数
                    'after' => [
                        'cla' => $this->get('cla'),
                        'fun' => ''
                    ],
                ],
                'href' => isset($result['href'])?$result['href']:'',
            ], 320));
            $res = auditClass::submitApprovalSignle($id,$body);
            if($res['warn'] == 1){
                return $res['data']; //自定义审批人
            }elseif($res['warn'] != 2){
                $_SESSION['warn'] = '提交失败，'.$res['warn'];
            }
        }
        return $resultJson;
    }

    /**
     * 详情页
     *
     * @return string
     */
    public function detail(): string
    {
        $info = query(self::table, " id = '" . $this->get('id') . "' ");
        if (!$this->power(self::page, "see")) {
            $html = L('salesContract.detail.power');
        } elseif (!$this->get('id')) {
            $html = L('salesContract.detail.IDEmpty');
        } elseif (!$info['id']) {
            $html = L('salesContract.detail.empty');
        } else {
            $data = [
                "id" => $info['id'],
                "menu" => [
                    "detail" => L('salesContract.detail.info'),
                    'contractTrack' => L('salesContract.detail.contractTrack'),
                    "file" => ["name" => L('salesContract.detail.file'), "cla" => "file", "fun" => "salesContractFile"],
                ]
            ];
            //按钮
            $button = [];
            if ($info['state'] == '草稿') {
                if ($this->power(self::page, "del")) {
                    $button[] = [
                        "name" => L('salesContract.detail.del'),
                        "type" => "弹出层",
                        "cla" => $this->get('cla'),
                        "fun" => "operate",
                        "post" => ["act" => 'del', "id" => $info['id']],
                    ];
                }
                if ($this->power(self::page, "edit")) {
                    $button[] = [
                        "name" => L('salesContract.detail.edit'),
                        "type" => "顶部页卡",
                        "title" => L('salesContract.detail.editContract'),
                        "url" => $this->root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=edit&id=' . $info['id'],
                        // 'style' => 'li-btn-blue-bg'
                    ];
                }
            }

            //审核按钮
            $button = array_merge($button, $this->auditButton($info));
            $tr[]     = [ '物料编码', '物料名称', '规格型号', '单位', '单价(' . static::$unit . ')', '数量','备注'];
            $result   = find(['table' => self::tableMx, 'where' => "orderId = '$info[id]' order by list"]);
            foreach ($result['array'] as $array) {
                $material = query('material', " id = '$array[materialId]'");
                $unit = $array['unit'];
                $num = self::lostZero($array['num'], 'pricePrecision');
                $price = self::lostZero($array['price'], 'pricePrecision');
                $text = $array['text'];
                $tr[]     = [
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    $unit,
                    $price,
                    $num,
                    $text
                ];
            }
            $kehu = query('kehu', " khid = '{$info['clientId']}' ");
            //生成表单
            $data['button'] = $this->tableShowButton($button);
            $data['html'] = $this->tableShow([
                L('salesContract.detail.info') => [
                    [
                        L('salesContract.homeSearch.orderNo') => $info['orderNo'],
                        L('salesContract.homeSearch.name') => $info['name'],
                        L('salesContract.homeSearch.clientName') => $kehu['companyName'],
                        '经办人' => self::findStaff($info['salesman']),
                    ],
                    [
                        L('salesContract.homeSearch.type') => $info['type'],
                        L('salesContract.homeSearch.signedDate') => self::formatDate($info['signedDate']),
                        L('salesContract.editPage.startDate') => self::formatDate($info['startDate']),
                        L('salesContract.editPage.endDate') => self::formatDate($info['endDate']),
                    ],
                    [
                        L('salesContract.editPage.text') => pre($info['text']),
                    ],
                ],
            ]);
            $data['html']   .= $this->detailList([
                'title' => '合同明细',
                'html'  => $this->listTable(['tr' => $tr, 'showEmpty' => true, 'total' => [], 'showSort' => true]),
            ]);
            $data['html'] .= $this->tableShow([
                L('salesContract.detail.sys') => [
                    [
                        L('salesContract.detail.stid') => self::findStaff($info['stid']),
                        L('salesContract.detail.time') => self::formatDate($info['time']),
                        L('salesContract.detail.updateTime') => self::null($info['updateTime']),
                    ]
                ],
                L('salesContract.detail.process') => [
                    [
                        auditClass::auditRecord(self::table, $info['id'])
                    ]
                ],
            ]);
            //生成页面
            $html = $this->tab($data);
        }
        //返回
        return $html;
    }

    /*列表页-查询条件*/
    public function contractTrackOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('salesContract.contractTrack.recordDate') => text(array("name" => "createTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                    L('salesContract.contractTrack.orderNo')   => text(array("name" => "orderNo")),
                    L('salesContract.contractTrack.companyName') => selectMultiple(["name" => "khid", 'table' => " kehu", 'sqlId' => 'khid', 'where' => "coid = '" . self::$coid . "' ", 'sqlField' => 'companyName']),
                ],
                [
                    L('salesContract.contractTrack.manager')  =>  selectMultiple(["name" => "stid", 'table' => " staff", 'sqlId' => 'stid', 'sqlField' => 'name']),
                    L('salesContract.contractTrack.name') => text(["name" => "name"]),
                    L('salesContract.contractTrack.code') => text(["name" => "code"]).
                        hidden(["name" => "orderId", 'value' => $this->get('id')]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /**
     * 合同跟踪
     */
    public function contractTrack(): bool|string
    {
        $html = $this->contractTrackOptions(false);
        $button = "  <a href='" . root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=exportData'>
                    <span class='spanButton'>".L('salesContract.contractTrackSearch.export')."</span>
                  </a>\n";
        $json['html'] = $this->search($html, layout: 'pop', toolButton: $button);
        return json_encode($json, 320);
    }

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            case 'contractTrackSearch':
                $tr = [
                    'recordDate'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.recordDate}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'orderNo' => [
                        'name'  => '{l.salesContract.contractTrackSearch.orderNo}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'contract'  => [
                        'name'  => '{l.salesContract.contractTrackSearch.contractNo}',
                        'width' => 200,
                    ],
                    'orderType'         => [
                        'name'  => '{l.salesContract.contractTrackSearch.orderType}',
                        'width' => 200,
                    ],
                    'companyName'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.companyName}',
                        'width' => 200,
                    ],
                    'manager'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.manager}',
                        'width' => 200,
                    ],
                    'code'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.code}',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'name'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.name}',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'model'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.model}',
                        'width' => 150,
                    ],
                    'unit'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.unit}',
                        'width' => 150,
                    ],
                    'num'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.sendNum}',
                        'width' => 150,
                    ],
                    'price'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.price}（' . static::$unit . '）',
                        'width' => 150,
                    ],
                    'money'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.money}（' . static::$unit . '）',
                        'width' => 150,
                    ],
                    'rate'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.rate}',
                        'width' => 150,
                    ],
                    'taxMoney'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.taxMoney}（' . static::$unit . '）',
                        'width' => 150,
                    ],
                    'moneyWithTax'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.moneyWithTax}（' . static::$unit . '）',
                        'width' => 150,
                    ],
                    'text'          => [
                        'name'  => '{l.salesContract.contractTrackSearch.text}',
                        'width' => 150,
                    ]
                ];
                break;
            case 'clientContractSearch':
                $tr = [
                    'signedDate'          => [
                        'name'  => '{l.salesContract.homeSearch.signedDate}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'orderNo' => [
                        'name'  => '{l.salesContract.homeSearch.orderNo}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'name'  => [
                        'name'  => '{l.salesContract.homeSearch.name}',
                        'width' => 200,
                    ],
                    'type'         => [
                        'name'  => '{l.salesContract.homeSearch.type}',
                        'width' => 200,
                    ],
                    'money'          => [
                        'name'  => '{l.salesContract.homeSearch.money}（' . static::$unit . '）',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'salesman'          => [
                        'name'  => '{l.salesContract.homeSearch.salesman}',
                        'width' => 200,
                    ],
                    'state'          => [
                        'name'  => '{l.salesContract.homeSearch.state}',
                        'width' => 150,
                    ]
                ];
                break;
            default:
                $tr = [
                    'signedDate'          => [
                        'name'  => '{l.salesContract.homeSearch.signedDate}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'orderNo' => [
                        'name'  => '{l.salesContract.homeSearch.orderNo}',
                        'width' => 200,
                        'sort' => 1,
                    ],
                    'name'  => [
                        'name'  => '{l.salesContract.homeSearch.name}',
                        'width' => 200,
                    ],
                    'clientName'  => [
                        'name'  => '{l.salesContract.homeSearch.clientName}',
                        'width' => 200,
                    ],
                    'type'         => [
                        'name'  => '{l.salesContract.homeSearch.type}',
                        'width' => 200,
                    ],
                    'state'          => [
                        'name'  => '{l.salesContract.homeSearch.state}',
                        'width' => 150,
                    ]
                ];
        }
        return $tr;
    }

    /**
     * 合同跟踪
     */
    public function contractTrackSearch(): bool|string
    {
        $id = $this->post('orderId');
        //查询结果
        $where = " main.contractId = '$id'  ";
        //生成查询语句
        $where .= search([
            "like" => [
                'code' => $this->post('code'),
                'name' => $this->post('name'),
                'orderNo' => $this->post('orderNo'),
            ],
            "=" => [
                'main.khid' => $this->post('khid'),
                "main.state" => '已确认'
            ],
        ]);
        if ($this->post('createTime')) {
            $where .= self::timeComparison($this->post('createTime'), 'date', 'main.recordDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search" => $this->post('list_sort_key') ?: 'a.list',
            "sort"   => $this->post('list_sort') ?: "desc",
            "array"  => array(),
        ));
        $page = $this->page([
            "table" => "sale_order as main join sale_order_detail as a on main.id = a.orderId join material as b on a.materialId = b.id",
            'field' => "b.*,main.contractId,main.isTax,a.id as mxId,a.orderId,a.id,a.price,a.num,a.money,a.rate,a.text,main.recordDate,main.orderNo,main.type as orderType,main.khid,main.manager",
            "where" => $where,
            "order" => $orderBy['orderBy']
        ]);
        $_SESSION[self::page]['sql'] = $page['fullSql'];
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array();
        //获取记录
        foreach ($page['array'] as $array) {
            $num = find(array(
                'table' => 'sale_send_order as a join sale_send_order_detail as b on a.id = b.orderId',
                'field' => "ifnull(sum(b.num),0) as num",
                'single' => "saleOrderMxId = '$array[mxId]' and state = '已确认'"
            ))['num'];
            $result = saleOrderClass::isTax($num, $array['price'], $array['rate'], $array['isTax']);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case "contract":
                        $contract = query('sales_contract', "id = '$array[contractId]'");
                        $row[] = $contract['orderNo'];
                        break;
                    case "companyName":
                        $kehu = query('kehu', "khid = '$array[khid]'");
                        $row[] = $kehu['companyName'];
                        break;
                    case "num":
                        $row[] = self::lostZero($num, 'numPrecision');
                        break;
                    case "price":
                        $row[] = self::lostZero($array['price'], 'pricePrecision');
                        break;
                    case "rate":
                        $rate = ($array['rate'] * 100) . '%';
                        $row[] = $rate;
                        break;
                    case "money":
                    case "taxMoney":
                    case "moneyWithTax":
                        $row[] = self::lostZero($result[$key]);
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        $button = "";
        //生成页面
        $li = $this->li(array(
            "body"        => $body,
            "install"     => $installSearch,
            "button"      => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page"        => $page['para'],
        ));
        //控件
        $json['html'] = $page['hint'] . $button . "<form name='mxForm'>" . $li . "</form>" . $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 导出
     */
    public function exportData()
    {
        $tr = [];
        $sql = $_SESSION[self::page]['sql'];
        $title = [L('salesContract.contractTrackSearch.recordDate'), L('salesContract.contractTrackSearch.orderNo'), L('salesContract.contractTrackSearch.contractNo'), L('salesContract.contractTrackSearch.orderType'), L('salesContract.contractTrackSearch.companyName'), L('salesContract.contractTrackSearch.manager'), L('salesContract.contractTrackSearch.code'), L('salesContract.contractTrackSearch.name'), L('salesContract.contractTrackSearch.model'), L('salesContract.contractTrackSearch.unit'), L('salesContract.contractTrackSearch.sendNum'), L('salesContract.contractTrackSearch.price').'（' . static::$unit . '）', L('salesContract.contractTrackSearch.money').'（' . static::$unit . '）', L('salesContract.contractTrackSearch.rate'), L('salesContract.contractTrackSearch.taxMoney').'（' . static::$unit . '）', L('salesContract.contractTrackSearch.moneyWithTax').'（' . static::$unit . '）', L('salesContract.contractTrackSearch.text')];
        $result = sqlFind($sql);
        if (is_array($result)) {
            foreach ($result as $array) {
                $num = find(array(
                    'table' => 'sale_send_order as a join sale_send_order_detail as b on a.id = b.orderId',
                    'field' => "ifnull(sum(b.num),0) as num",
                    'single' => "saleOrderMxId = '$array[mxId]' and state = '已确认'"
                ))['num'];
                $rate = ($array['rate'] * 100) . '%';
                $kehu = query('kehu', "khid = '$array[khid]'");
                $contract = query('sales_contract', "id = '$array[contractId]'");
                $result = saleOrderClass::isTax($num, $array['price'], $array['rate'], $array['isTax']);
                $tr[] = [
                    $array['recordDate'],
                    $array['orderNo'],
                    $contract['orderNo'],
                    $array['orderType'],
                    $kehu['companyName'],
                    self::findStaff($array['manager']),
                    $array['code'],
                    $array['name'],
                    $array['model'],
                    $array['unit'],
                    self::lostZero($num, 'numPrecision'),
                    self::lostZero($array['price'], 'pricePrecision'),
                    self::lostZero($result['money'], 'amount'),
                    $rate,
                    self::lostZero($result['taxMoney'], 'amount'),
                    self::lostZero($result['moneyWithTax'], 'amount'),
                    $array['text']
                ];
            }
        }
        $text = str_replace(['{{staffName}}'], [$this->control['name']], L('salesContract.exportData.log'));
        $this->logText(["type" => self::page, "text" => $text]);
        $this->excelOut($title, $tr, L('salesContract.exportData.fileName').".xlsx");
        header("Location:" . getenv("HTTP_REFERER"));
        exit(0);
    }

    /*列表页-查询条件*/
    public function contractMxOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('salesContract.contractTrack.code') => text(array("name" => "code")),
                    L('salesContract.contractTrack.name')   => text(array("name" => "name")),
                    L('salesContract.contractTrackSearch.model')   => text(array("name" => "model")).
                        hidden(["name" => "orderId", 'value' => $this->get('id')?$this->get('id'):$this->post('id')]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    public static function updateJs()
    {
        return <<<eof
<script>
//通过单价计算金额，税额等
function countMoney(e){
    let trObj = $(e).parent().parent();
    countProcess(trObj)
}
function countProcess(trObj){
    let price = trObj.find("[name='price']").val();
    let num = trObj.find("[name='num']").val();
    let rate = trObj.find("[name='rate']").val();
    rate = Number(rate)/100;
    let money;
    let taxMoney,moneyWithTax;
    if($("[name='isTax']").is(":checked")){
       //含税单价
       taxMoney = (Number(price)*Number(num)/(1+rate)*rate).toFixed(amountPrecision);
       moneyWithTax = (Number(price)*Number(num)).toFixed(amountPrecision);
       money = Number(moneyWithTax-taxMoney).toFixed(amountPrecision)
    }else{
       //未含税单价
        taxMoney = (Number(price)*Number(num)*rate).toFixed(amountPrecision);
        moneyWithTax = (Number(price)*Number(num)*(1+rate)).toFixed(amountPrecision);
        money = (Number(price)*Number(num)).toFixed(amountPrecision);
    }
    trObj.find(".noTaxMoney").html(money)
    trObj.find(".taxMoney").html(taxMoney)
    trObj.find("[name='money']").val(moneyWithTax)
}
//通过价税合计计算单价
function calculatePrice(e){
    let trObj = $(e).parent().parent();
    let moneyWithTax = e.value;//价税合计
    let num = trObj.find("[name='num']").val();
    let rate = trObj.find("[name='rate']").val();
    if(num > 0){
        rate = Number(rate)/100;
        let taxMoney,price,money;
        taxMoney = (moneyWithTax/(1+rate)*rate);//税额
        if($("[name='isTax']").is(":checked")){
           //含税
           price = moneyWithTax/num;
           money = moneyWithTax-taxMoney;
        }else{
           //未含税
            price = (moneyWithTax-taxMoney)/num;
            money = moneyWithTax-taxMoney;
        }
        
        trObj.find(".noTaxMoney").html(money.toFixed(amountPrecision))
        trObj.find(".taxMoney").html(taxMoney.toFixed(amountPrecision))
        trObj.find("[name='price']").val(price.toFixed(amountPrecision))
    }
}

// 单个文本框更新
function textUpdate(obj, cla, fun) {
    let field = $(obj).attr('name'), val = $(obj).val()
    if (field.length > 0 && val.length > 0) {
        const url = root + 'control/adIndex.html?cla=' + cla + '&fun=' + fun
        let params = {}
        // 判断是否有data-* 参数
        if ($(obj).data()) {
            Object.assign(params, $(obj).data())
            params[field] = val
        }
        $.post(url, params, function (resp) {
            if (resp.warn === 2) {
                if (field !=='money'){
                      countMoney(obj)
                }
                if (resp.href) {
                    window.location.href = resp.href;
                } else {
                    msg(resp.msg)
                }
            } else {
                warn(resp.warn)
            }
        }, "json");
    }
}
//切换含税不含税复选框
function taxChange(id){
    let isTax = $("[name='isTax']").is(":checked") ? 1 : 0
    $.post(root+'control/adIndex.html?cla=salesContract&fun=taxChange',{id: id,isTax: isTax},function(res) {
        $("[name='contractMxForm'] [name='price']").each(function() {
           textUpdate($(this),'salesContract','updateMx')
        })
    },'json');
}
</script>
eof;
    }

    // 修改是否含税
    public function taxChange()
    {
        // 更新字段
        $field = [
            'isTax' => $this->post('isTax'),
        ];
        $info = query(self::table, " id = '{$this->post('id')}' ");
        $state = '草稿';
        if ($info['state'] != $state) {
            $json['warn'] = str_replace(['{{state}}'], [$state], L('salesContract.updateMx.stateError'));
        } else {
            $warn = static::update([
                'table' => self::table,
                'field' => $field,
                'where' => " id = '{$this->post('id')}' ",
            ], false);
            if ($warn == '更新成功') {
                $json['warn'] = 2;
                $json['msg'] = $warn;
            } else {
                $json['warn'] = $warn;
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 添加产品
     * @return bool|string
     */
    public function addMx()
    {
        $html =
            materialClass::typeSelect() .
            text(["name" => "code", "title" => "产品编码"]) .
            text(["name" => "materialName", "title" => "产品名称"]) .
            text(["name" => "model", "title" => "规格型号"]) .
            hidden(['name' => 'materialId', 'value' => $this->post('materialId') ? implode(',', $this->post('materialId')) : '']);
        $type = 'material';
        $layerId  = $this->get('cla') . ucwords($this->get('fun'));
        $formName = 'mxForm';
        $button   = "<input onclick=\"addRow('$type');removeSelectedContent('" . $formName . "')\" type='button' class='searchSub m-l-5' value='继续添加'>";
        $button   .= "<input onclick=\"addRow('$type');$('#" . $layerId . "').remove()\" type='button' class='searchSub m-l-5' value='提交'>";
        $html     = $this->search($html);
        return $this->layer(["title" => "添加", "height" => 600, "width" => 1000, "html" => $html, "button" => $button]);
    }

    /**
     *添加产品
     */
    public function addMxSearch()
    {
        $materialId    = $this->post('materialId') ? explode(',', $this->post('materialId')) : [];
        $where         = " 1=1 and a.id not in ('" . implode("','", $materialId) . "')";
        $like          = [
            'a.name'          => $this->post('materialName'),
            'code'            => $this->post('code'),
            'model'           => $this->post('model'),
            'a.typePath'      => $this->post('materialTypeId'),
            'a.supplyControl' =>  '允许销售',
        ];
        $equal         = [
            'a.state' => '启用',
        ];
        $contractMatId = [];
        $where .= " and a.coid = '" . self::$coid . "'";
        $where       .= search(["like" => $like, "=" => $equal]);
        $page        = $this->page([
            "table"   => "material as a",
            "field"   => "a.*",
            "where"   => $where,
            'pageNum' => 12,
            "order"   => !$this->post('buttonType') ? "a.code ASC" : "field (a.id,'" . implode("','", $contractMatId) . "')",
        ]);
        //获取表头
        $checkAll = $this->checkAll("mxForm", "mxId");
        $tr[]     = [$checkAll, '分类', '产品编码', '产品名称', '规格型号'];
        //获取记录
        foreach ($page['array'] as $array) {
            $dominate = [
                "box" => ["name" => "mxId", "value" => $array['id']],
            ];
            $checkBox = $this->dominate($dominate);
            if (!empty($this->post('buttonType')) && $array['coid'] != self::$coid) {
                $checkBox = "<span class='no-choose'>--</span>";
            }
            $tr[] = [
                $checkBox,
                $array['typeName'],
                $array['code'],
                $array['name'],
                $array['model'],
            ];
        }
        $json['html'] = $page['hint'] .
            "<form name='mxForm'>" .
            $this->tableMany(["tr" => $tr, "showSort" => true, "page" => $page['para']]) .
            "</form>" .
            $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 关联报价单
     * @return bool|string
     */
    public function addQuotationsMx()
    {
        $callback = $this->post('callback') ? $this->post('callback') : self::page;
        $tableMx = $this->post('tableMx');
        $html =
            text(["name" => "orderNo", "title" => "{l.salesContract.addQuotationsMx.orderNo}"]) .
            text(["name" => "description", "title" => "{l.salesContract.addQuotationsMx.description}"]) .
            text(['name' => 'startDate', 'title' => '{l.salesContract.addQuotationsMx.startDate}', 'class' => 'text width200', 'laydate' => ['range' => '~', 'type' => 'date'],]) .
            text(['name' => 'endDate', 'title' => '{l.salesContract.addQuotationsMx.endDate}', 'class' => 'text width200', 'laydate' => ['range' => '~', 'type' => 'date'],])
            . hidden(["name" => "tableMx", 'value' => $tableMx])
            . hidden(["name" => "type", 'value' => 'quotations'])
            . hidden(['name' => 'orderId', 'value' => $this->post('orderId')]);
        $button = "<input onclick=\"subForm('quotationsForm', '" . root . "control/adIndex.html?cla=" . $callback . "&fun=addMxEdit');\" type='button' class='searchSub m-l-5' value='".L('salesContract.addQuotationsMx.sub')."'>";
        $html = $this->search($html);
        return $this->layer(["title" => L('salesContract.addQuotationsMx.add'), "height" => 600, "width" => 1100, "html" => $html, "button" => $button]);
    }

    /**
     * 关联报价单
     */
    public function addQuotationsMxSearch()
    {
        $id = $this->post('orderId');
        $where = "state = '已确认' and coid='".self::$coid."'";
        $and = "";
        $like = [
            'name' => $this->post('orderNo'),
            'code' => $this->post('description'),
            'model' => $this->post('model'),
        ];
        if ($this->post('startDate')) {
            $where .= self::timeComparison($this->post('startDate'), 'date', 'startDate');
        }
        if ($this->post('endDate')) {
            $where .= self::timeComparison($this->post('endDate'), 'date', 'endDate');
        }
        $where .= search(["like" => $like]) . $and;

        $page = $this->page([
            "table" => 'quotations',
            "where" => $where,
            'pageNum' => 50,
            "order" => " `time` ASC",
        ]);
        //获取表头
        $checkAll = $this->checkAll("mxForm", "mxId");
        $tr[] = [$checkAll, L('salesContract.addQuotationsMxSearch.orderNo'), L('salesContract.addQuotationsMxSearch.description'), L('salesContract.addQuotationsMxSearch.recordDate'), L('salesContract.addQuotationsMxSearch.endDate')];
        //获取记录
        foreach ($page['array'] as $array) {
            $dominate = array(
                "box" => array("name" => "mxId", "value" => $array['id']),
            );
            $tr[] = [
                $this->dominate($dominate),
                $array['orderNo'],
                $array['description'],
                $array['recordDate'],
                $array['endDate'],
            ];
        }
        $json['html'] = $page['hint'] .
            "<form name='quotationsForm'>" .
            hidden(['name' => 'id', 'value' => $id]) .
            hidden(['name' => 'type', 'value' => $this->post('type')]) .
            $this->tableMany(array("tr" => $tr, "showSort" => true, "page" => $page['para'])) .
            "</form>" .
            $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 编辑
     * 添加
     * @return bool|string
     */
    public function addMxEdit()
    {
        $mxIdArr    = $this->post('mxId');
        if (!$this->power(self::page, 'edit')) {
            $json['warn'] = '你还没有编辑权限';
        } elseif (empty($mxIdArr) || !is_array($mxIdArr)) {
            $json['warn'] = '请选择产品';
        } else {
            $tr = [];
            foreach ($mxIdArr as $mxId) {
                $material   = query('material', "id = '$mxId'");
                $unit                         = $material['unit'];
                $price             = self::formattingFigure($material['salePrice'], 'pricePrecision');
                $suiji             = self::getId();
                $tr[]              = [
                    componentClass::tablePperation('', "delTableRow(this);calculateTotal()") .
                    hidden(['name' => 'mxId[]', 'value' => $suiji]) .
                    hidden(['name' => 'materialId[]', 'value' => $mxId]),
                    $material['code'],
                    $material['name'],
                    $material['model'],
                    select(['name' => 'unit[]', 'data' => ['unit' => $unit], 'change' => 'unitChange', 'value' => $unit, 'option' => machiningOrderClass::unitOption($material['id'])]),
                    text(['name' => 'price[]', 'type' => 'text', 'blur' => 'countMoney', 'other' => self::digitalFiltering('pricePrecision'), 'value' => $price]),
                    text(['name' => 'num[]', 'type' => 'text', 'other' => self::digitalFiltering('int'), 'value' => '']),
                    text(['name' => 'mxText[]', 'class' => 'text textPrice']),
                ];
            }
            $json['html'] = $this->tableMany(['tr' => $tr, 'thead' => false]);
            $json['warn'] = 2;
        }
        return json_encode($json, 320);
    }

    public function deleteMx()
    {
        // 条件字段
        $wField = [
            'id' => $this->post('id'),
            'orderId' => $this->post('orderId'),
        ];
        $info = query(self::table, " id = '{$wField['orderId']}' ");
        $state = '草稿';
        if ($info['state'] != $state) {
            $json['warn'] = str_replace(['{{state}}'], [$state], L('salesContract.deleteMx.stateError'));
        } else {
            $warn = delete([
                'table' => self::tableMx,
                'where' => generateWhere($wField),
            ]);
            $json['warn'] = ($warn == '删除成功') ? 2 : $warn;
            $json['href'] = root . 'control/adIndex.html?cla=salesContract&fun=detail&id=' . $wField['orderId'] . '&menu=contractMx';
        }
        return json_encode($json, 320);
    }

    public function updateMx()
    {
        // 条件字段
        $wField = [
            'id' => $this->post('id'),
            'orderId' => $this->post('orderid'),
        ];
        // 更新字段
        $field = [
            'unit' => $this->post('unit'),
            'aliasNo' => $this->post('aliasNo'),
            'aliasName' => $this->post('aliasName'),
            'num' => $this->post('num') ? self::formattingFigure($this->post('num'), 'numPrecision') : '',
            'price' => $this->post('price') ? self::formattingFigure($this->post('price'), 'pricePrecision') : '',
            'rate' => $this->post('rate') ? (float)$this->post('rate') / 100 : '',
            'text' => $this->post('text'),
        ];
        $info = query(self::table, " id = '{$wField['orderId']}' ");
        $state = '草稿';
        if ($info['state'] != $state) {
            $json['warn'] = str_replace(['{{state}}'], [$state], L('salesContract.updateMx.stateError'));
            /*} elseif (static::total(array('table' => self::tableMx, 'where' => "orderId = '$info[id]' and materialId = '$field[materialId]'")) > 0) {
                $json['warn'] = L('salesContract.updateMx.attrRepeat');*/
        } else {
            $where = generateWhere($wField);
            $mx = query(self::tableMx, $where);
            if ($field['num'] || $field['price'] || $field['rate'] || $this->post('money')) {
                if ($this->post('money')) {
                    $taxMoney = self::formattingFigure($this->post('money') / (1 + $mx['rate']) * $mx['rate']);//税额
                    $field['price'] = self::formattingFigure(($this->post('money') - $taxMoney) / $mx['num']);
                }
                $result = saleOrderClass::isTax($field['num'] ?: $mx['num'], $field['price'] ?: $mx['price'], $field['rate'] ?: $mx['rate']);
                $field['taxMoney'] = $result['taxMoney'];
                $field['moneyWithOutTax'] = $result['money'];
                $field['money'] = $this->post('money') ?: $result['moneyWithTax'];
            }

            $warn = static::update([
                'table' => self::tableMx,
                'field' => $field,
                'where' => $where,
            ], false);
            if ($warn == '更新成功') {
                $json['warn'] = 2;
                $json['msg'] = $warn;
            } else {
                $json['warn'] = $warn;
            }

        }
        return json_encode($json, 320);
    }


    // 操作中转
    public function operate()
    {
        $act = $this->post('act') ?? '';
        $pwd = false; // 需要密码
        $form = $power = '';
        $append = [];
        switch ($act) {
            case 'changeState':
                // $act = 'edit';
                // $msg = self::title.'修改状态';
                // $title = '';
                // $function = 'changeState';
                // $form = self::page.'OperateForm, listForm';
                // if ($this->post('state') == '已发布') {
                //     $title = self::page.'Change';
                // } else {
                //     $info = query(self::table, " id = '{$this->post('id')}' ");
                //     $append = [
                //         must.'发布范围：'  =>
                //         selectMultiple(["name" => "viewScope[]", 'table' => " staff", 'sqlId' => 'stid', 'sqlField' => 'name', 'title' => '查看范围', 'value'    => implode(',', (array) json_decode($info['viewScope'], true)), 'multiple' => true,]).space
                //     ];
                // }
                $power = '';
                break;
            default:
                $act = 'del';
                $msg = L('salesContract.operate.del');
                $title = self::page . 'Delete';
                $function = 'isDelete';
                $form = self::page . 'OperateForm,listForm,contractForm';
                $power = '';
                break;
        }
        if (!$this->power(self::page, $act)) {
            $_SESSION['warn'] = str_replace(['{{msg}}'], [$msg], L('salesContract.operate.warn'));
            $json = [
                'warn' => 2,
                'href' => root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=home',
            ];
        } else {
            return $this->confirm([
                'title' => $title,
                'function' => $function,
                'form' => $form,
                'power' => $power,
                'pwd' => $pwd,
                'append' => $append,
            ]);
        }

        resp:
        return json_encode($json, 320);
    }

    // 确认删除信息
    public function isDelete()
    {
        $array = $this->post('listId') ?? $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = L('salesContract.isDelete.power');
        } elseif (empty($array)) {
            $json['warn'] = L('salesContract.isDelete.noChoice');
        } else {
            $text = '';
            $x = 0;
            $array = is_array($array) ? $array : [$array];
            // 判断field
            $fieldKey = 'state';
            $fieldVlaue = '草稿';

            foreach ($array as $id) {
                $where = " id = '$id' ";
                $info = query(self::table, $where);
                if ($info['id']) {
                    if ($info[$fieldKey] !== $fieldVlaue) {
                        $text .= str_replace(['{{id}}','{{fieldVlaue}}'], [$info['id'],$fieldVlaue], L('salesContract.isDelete.text')) . "<br>";
                        continue;
                    }
                    // 删除相关 附件
                    $result = find(['table'=>'file','where'=>"targetId = '{$info['id']}'"]);
                    foreach ($result['array'] as $key => $attachFile) {
                        delete([
                            'table' => 'file',
                            'where' => " id = '{$attachFile['id']}'",
                        ]);
                        fileDelete($attachFile['src']);
                    }
                    // 删除子表
                    delete([
                        "table" => self::tablePay,
                        "where" => " orderId = '$id' "
                    ]);
                    delete([
                        "table" => self::tableMx,
                        "where" => " orderId = '$id' "
                    ]);
                    delete([
                        "table" => self::tableAddr,
                        "where" => " orderId = '$id' "
                    ]);
                    // 删除表
                    delete([
                        "table" => self::table,
                        "where" => $where
                    ]);
                    //添加记录
                    $text .= str_replace(['{{staffName}}','{{id}}','{{name}}'], [$this->control['name'],$id,$info['name']], L('salesContract.isDelete.log')) . "<br>";
                    $x++;
                }
            }

            // 写入日志
            $this->logText(["type" => self::page, "text" => $text]);
            $_SESSION['warn'] = str_replace(['{{x}}'], [$x], L('salesContract.isDelete.warn'));
            $json['warn'] = 2;
            $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }

        resp:
        return json_encode($json, 320);
    }
}
